﻿
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Excel.Expressions;
using Excel.Expressions.Classes;
using Excel.Expressions.Compiler;
using Expressions.Compiler;
using Expressions.Compiler.Internal;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NonterminalExpressions = Excel.Expressions.Expressions;
using Excel.Expressions.Tests;

namespace Tests
{


    /// <summary>
    ///This is a test class for Test5_ and is intended
    ///to contain all Test5_ Unit Tests
    ///</summary>
    [TestClass()]
    public class Test5
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for Nonterminal<char> Constructor
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_1()
        {
            Nonterminal<char> target = "G";
            Assert.AreNotEqual(target, null);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_2()
        {
            Nonterminal<char> target = "target";
            Nonterminal<char> G = "null_G";
            G.Definition = new Rules<char>
            {
                () => "890".ToCharArray()
            };
            target.Definition = new Rules<char>
            {
                () => G[true]
            };

            target.Initialize();
            target.Validate();

            Parser<char> input = new char[] { Terminal<char>.Default };
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == false;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_3()
        {
            Nonterminal<char> target = "target";

            Nonterminal<char> G = "G";
            G.Definition = new Rules<char>
            {
                { () => "890".ToCharArray() }
            };
            target.Definition = new Rules<char>
            {
                () => !G[false]
            };

            target.Initialize();
            target.Validate();

            Parser<char> input = "890".ToCharArray();
            bool expected = true;
            bool actual = target.Parse(input) == true;

            Assert.AreEqual(expected, actual);
        }


        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_4()
        {
            Nonterminal<char> target = "target";

            Nonterminal<char> G = "?G";
            G.Definition = new Rules<char>
            {
                () => 
                {
                    return "!!!".ToCharArray();
                }
            };
            target.Definition = new Rules<char>
            {
                () => 
                {
                    return !G[false];
                }
            };

            target.Initialize();
            target.Validate();

            Parser<char> input = '\0';
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == false;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_5()
        {
            Terminal<char>[] _ = { '\0' };

            Nonterminal<char> grammar = "G";
            grammar.Definition = new Rules<char> 
            {
                () => '\0'
            };

            grammar.Initialize();
            grammar.Validate();

            Entity<char> target = grammar;

            Parser<char> input = "\0".ToCharArray();
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == false;
            Assert.AreEqual(expected, actual);
        }

#if TRACE
        /// <summary>
        ///A test for ToString
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_6()
        {
            Nonterminal<char> target = "G";
            string expected = "G";
            string actual;
            actual = target.Name;
            Assert.AreEqual(expected, actual);
        }
#endif

        /// <summary>
        ///A test for Item
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_7()
        {
            Nonterminal<char> target = "G";
            bool optional = false;
            Tokens<char> actual;
            actual = target[optional];
            Assert.AreNotEqual(actual, null);
        }


#if DEBUG
        
#if TRACE  
        /// <summary>
        ///A test for Item
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_8()
        {
            Nonterminal<char> target = Nonterminals.cell_assigment_expression;
            Parser<char> parser = "A0=SUM(A1)".ToCharArray();

            target.Initialize();
            target.Validate();

            target.Parse(parser);
            bool expected = true;
            bool actual = string.Equals(target.ToString(), "cell-assigment-expression[t]");
            Assert.AreEqual(expected, actual);
        }
        
        /// <summary>
        ///A test for Item
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_9()
        {
            Cell A0 = Cell.GetCell(0, 0);
            Cell A1 = Cell.GetCell(0, 0);
            A0.Clear();
            A1.Clear();
            Nonterminal<char> target = Nonterminals.cell_assigment_expression;
            Parser<char> parser = "A0=SUM(A1)".ToCharArray();

            target.Initialize();
            target.Validate();

            target.Parse(parser);
            bool expected = true;
            bool actual = string.Equals(target[true].ToString(), "(cell-assigment-expression[t])");
            Assert.AreEqual(expected, actual);
        }
#endif


        /// <summary>
        ///A test for Item
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_10()
        {
            Cell A0 = Cell.GetCell(0, 0);
            Cell A1 = Cell.GetCell(0, 0);
            Cell cell = A0;
            A0.Clear();
            A1.Clear();
            Nonterminal<char> target = Nonterminals.cell_assigment_expression;
            Expression<char, CellExpression> expression = NonterminalExpressions.cell_assigment_expression;

            Parser<char> parser = "A0=SUM(A1)".ToCharArray();

            target.Initialize();
            target.Validate();

            target.Parse(parser);
            Assignment instruction = expression[parser.Tree] as Assignment;
            CellReference reference = instruction.CellReference;
            Cell current = reference.Cell;
            current.Text = instruction.Text;
            current.Expression = instruction.Expression;
            bool expected = true;
            bool actual = string.Equals(string.Format("{0} : {1} = {2}", cell, cell.Expression, cell.Value), "A0 : SUM(A1) = 0");
            Assert.AreEqual(expected, actual);
        }
#else
        /// <summary>
        ///A test for Item
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_10()
        {
            Cell A0 = Cell.GetCell(0, 0);
            Cell A1 = Cell.GetCell(0, 0);
            Cell cell = A0;
            A0.Clear();
            A1.Clear();
            Nonterminal<char> target = Nonterminals.cell_assigment_expression;
            Expression<char, CellExpression> expression = NonterminalExpressions.cell_assigment_expression;
            Parser<char> parser = "A0=SUM(A1)".ToCharArray();

            target.Initialize();
            target.Validate();

            target.Parse(parser);
            Assignment instruction = expression[parser.Tree] as Assignment;
            CellReference reference = instruction.CellReference;
            Cell current = reference.Cell;
            current.Text = instruction.Text;
            current.Expression = instruction.Expression;
            bool expected = true;
            bool actual = string.Equals(string.Format("{0} = {1}", cell, cell.Value), "A0 = 0");
            Assert.AreEqual(expected, actual);
        }
#endif

#if TRACE
        /// <summary>
        ///A test for Item
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_11()
        {
            Cell A0 = Cell.GetCell(0, 0);
            Cell A1 = Cell.GetCell(0, 0);
            Cell cell = A0;
            A0.Clear();
            A1.Clear();
            Nonterminal<char> target = Nonterminals.cell_assigment_expression;
            Parser<char> parser = "A0=SUM(A1)".ToCharArray();

            target.Initialize();
            target.Validate();

            Parser<char>.ClearTraceLog();

            target.Parse(parser);

            Parser<char>.WriteTraceLog();

            bool expected = true;
            bool actual = string.Equals(parser.Tree.ToString(), "[ cell-assigment-expression[t] ] A0=SUM(A1)");
            Assert.AreEqual(expected, actual);
        }
        /// <summary>
        ///A test for null
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_12()
        {
            char[] ch = null;
            string key = Terminal<char>.Default.ToString();
            Parser<char> text = (Parser<char>)ch;
            Terminal<char> terminal = ((Terminal<char>)ch)[true];
            text = "(|)".ToCharArray();
            string expected = "(|)";
            string actual = terminal.ToString();
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Item
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_14()
        {
            Nonterminal<char> target = Nonterminals.cell_assigment_expression;
            Parser<char> parser = "A0=SUM(A1)".ToCharArray();

            target.Initialize();
            target.Validate();

            target.Parse(parser);
            Tokens<char> tokens = target[false];
            IEnumerator<Token<char>> enumerator = tokens.Items.GetEnumerator();
            enumerator.MoveNext();
            Token<char> token = enumerator.Current;
            bool expected = true;
            bool actual = string.Equals(token.ToString(), "cell-assigment-expression[t]");
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Item
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_15()
        {
            Nonterminal<char> target = Nonterminals.cell_assigment_expression;
            Parser<char> parser = "A0=SUM(A1)".ToCharArray();

            target.Initialize();
            target.Validate();

            target.Parse(parser);
            Tokens<char> tokens = target[false];
            IEnumerator<Token<char>> enumerator = tokens.Items.GetEnumerator();
            enumerator.MoveNext();
            Token<char> token = enumerator.Current;
            bool expected = true;
            bool actual = string.Equals(token.Entity.ToString(), "cell-assigment-expression[t]");
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Item
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_16()
        {
            Nonterminal<char> target = Nonterminals.cell_assigment_expression;
            Parser<char> parser = "A0=SUM(A1)".ToCharArray();
            target.Initialize();
            target.Parse(parser);
            Tokens<char> tokens = target[true];
            IEnumerator<Token<char>> enumerator = tokens.Items.GetEnumerator();
            enumerator.MoveNext();
            Token<char> token = enumerator.Current;
            bool expected = true;
            bool actual = string.Equals(token.Entity.ToString(), "(cell-assigment-expression[t])");
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Item
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_17()
        {
            Parser<char> parser = "A0=SUM(A1)".ToCharArray();
            bool expected = true;
            bool actual = string.Equals(parser.Current.ToString(), "A");
            Assert.AreEqual(expected, actual);
        }
#endif

        /// <summary>
        ///A test for Item
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test5_18()
        {
            Nonterminal<char> boolTarget = "bool[t]";
            boolTarget.Definition = new Rules<char>()
            {
                () => '0',
                () => '1',
            };

            Expression<char, BooleanInt> boolExpression = "bool[t]";
            boolExpression.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals('0') || b[0].Context.Token.Equals('1'))
                {
                    return new BooleanInt(b[0].Context.ToString());
                }
                throw new NotSupportedException("Input token is not supported");
            };

            Parser<char> boolParser = "0".ToCharArray();
            boolTarget.Initialize();
            boolTarget.Validate();

            bool expected = true;
            bool actual = boolTarget.Parse(boolParser);

            bool result = boolExpression[boolParser.Tree].Value;
            Assert.AreEqual(false, result);
            Assert.AreEqual(expected, actual);
        }
    }
}
